package com.dag.account.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dag.account.api.dto.recharge.ApplyRechargeReqDTO;
import com.dag.account.api.dto.recharge.ApplyRechargeRespDTO;
import com.dag.account.api.dto.recharge.PayCallbackParamDTO;
import com.dag.account.constants.*;
import com.dag.account.dao.entity.Account;
import com.dag.account.dao.entity.Member;
import com.dag.account.dao.entity.RechargeBill;
import com.dag.account.dao.entity.TradeRecord;
import com.dag.account.dao.mapper.RechargeBillMapper;
import com.dag.account.service.*;
import com.dag.account.utils.TradeUtils;
import com.dag.seqno.Sequence;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;

/**
 * @author chien
 * @since 2020-07-23
 */
@Slf4j
@Service
public class RechargeBillServiceImpl extends ServiceImpl<RechargeBillMapper, RechargeBill> implements IRechargeBillService {

    @Autowired
    private IAccountService accountService;
    @Autowired
    private ITradeRecordService tradeRecordService;
    @Autowired
    private IFundPoolService fundPoolService;
    @Autowired
    private IPlatformService platformService;
    @Autowired
    private IMemberService memberService;
    @Autowired
    private Sequence sequence;

    /**
     * 申请充值
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApplyRechargeRespDTO applyRecharge(ApplyRechargeReqDTO applyRechargeDTO) {
        Account account = accountService.getById(applyRechargeDTO.getAccountId());

        ApplyRechargeRespDTO rechargeRespDTO = this.validateRecharge(applyRechargeDTO, account);

        Member member = memberService.getById(account.getMemberId());

        // 生成充值记录
        RechargeBill rechargeBill = new RechargeBill();
        rechargeBill.setRechargeNo(sequence.getFixedLengthSeqNo("acc_recharge_bill", 8, "R"));
        rechargeBill.setAccountId(account.getId());
        rechargeBill.setMemberId(member.getId());
        rechargeBill.setMemberName(member.getMemberName());
        rechargeBill.setMoney(applyRechargeDTO.getAmount());
        rechargeBill.setRechargeStatus(RechargeStatusEnum.RECHARGING.getIndex());
        rechargeBill.setTradeChannel(applyRechargeDTO.getTradeChannel());
        rechargeBill.setCreateTime(new Date());
        rechargeBill.setOrgId(account.getOrgId());
        rechargeBill.setMerchantId(account.getMerchantId());
        save(rechargeBill);

        // 返回编码
        rechargeRespDTO.setRechargeNo(rechargeBill.getRechargeNo());
        return rechargeRespDTO;
    }

    /**
     * 充值支付回调
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean rechargeCallback(PayCallbackParamDTO payCallbackParamDTO) {
        log.info("充值回调参数{}", payCallbackParamDTO);
        String rechargeNo = payCallbackParamDTO.getOutBillNo();
        BigDecimal rechargeAmount = payCallbackParamDTO.getMoney();

        // 查询充值记录
        RechargeBill rechargeBill = queryByRechargeNo(rechargeNo);
        if(rechargeBill == null){
            log.info("充值记录不存在");
            return false;
        }

        // 如果已经处理过 直接返回
        if(rechargeBill.getRechargeStatus() == RechargeStatusEnum.SUCCESS.getIndex()){
            return true;
        }

        String accountId = rechargeBill.getAccountId();
        String memberName = rechargeBill.getMemberName();

        // 更新充值记录
        rechargeBill.setRechargeStatus(RechargeStatusEnum.SUCCESS.getIndex());
        rechargeBill.setPayTime(new Date());
        updateById(rechargeBill);

        // 平台收款账户增加一笔
        Account platformAccount = platformService.queryPlatformAccount();
        Member platformMember = platformService.queryPlatformMember();
        accountService.add(platformAccount, rechargeAmount, memberName);

        // 资金池加钱
        fundPoolService.add(rechargeAmount, memberName);

        // 充值账户加钱
        Account account = accountService.getById(accountId);
        accountService.add(account, rechargeAmount, memberName);

        // 生成充值交易记录
        TradeRecord tradeRecord = new TradeRecord();
        tradeRecord.setSerialNo(TradeUtils.buildSeqNo());
        tradeRecord.setTradeVoucherNo(payCallbackParamDTO.getOutBillNo());
        tradeRecord.setAccountId(rechargeBill.getAccountId());
        tradeRecord.setMemberId(rechargeBill.getMemberId());
        tradeRecord.setMemberName(memberName);
        tradeRecord.setOtherAccountId(platformAccount.getId());
        tradeRecord.setOtherMemberId(platformMember.getId());
        tradeRecord.setOtherMemberName(platformMember.getMemberName());
        tradeRecord.setTradeType(TradeTypeEnum.RECHARGE.getIndex());
        tradeRecord.setTradeTypeName(TradeTypeEnum.RECHARGE.getText());
        tradeRecord.setTradeChannel(rechargeBill.getTradeChannel());
        tradeRecord.setAmount(rechargeAmount.abs());
        tradeRecord.setTradeSubject("账户充值");
        tradeRecord.setTradeContent(account.getAccountTypeName() + "充值");
        tradeRecord.setFundFlowType(FundFlowTypeEnum.INCOME.getIndex());
        tradeRecord.setTradeStatus(TradeStatusEnum.TRADE_STATUS_SUCCESS.getIndex());
        tradeRecord.setTradeTime(new Date());
        tradeRecord.setCreateTime(new Date());
        tradeRecord.setOrgId(rechargeBill.getOrgId());
        tradeRecord.setMerchantId(rechargeBill.getMerchantId());
        // 生成平台交易记录
        TradeRecord otherTradeRecord = TradeUtils.copyAndReverse(tradeRecord);
        tradeRecordService.saveBatch(Lists.newArrayList(tradeRecord, otherTradeRecord));
        return true;
    }


    @Override
    public RechargeBill queryByRechargeNo(String rechargeNo) {
        RechargeBill rechargeBill = new RechargeBill();
        rechargeBill.setRechargeNo(rechargeNo);
        return getOne(new QueryWrapper<>(rechargeBill));
    }


    /**
     * 校验充值
     */
    private ApplyRechargeRespDTO validateRecharge(ApplyRechargeReqDTO rechargeReqDTO, Account account){
        String accountId = rechargeReqDTO.getAccountId();
        BigDecimal amount = rechargeReqDTO.getAmount();
        if(account == null){
            return ApplyRechargeRespDTO.byFail(accountId, amount, "充值账户不存在");
        }
        Integer accountStatus = account.getStatus();
        if(accountStatus != AccountStatusEnum.VALID.getIndex()){
            return ApplyRechargeRespDTO.byFail(accountId, amount, "充值账户状态异常");
        }
        return ApplyRechargeRespDTO.bySuccess(accountId, amount, "校验通过");
    }

}
